type MMap = {
  [key: string]: any
}
type DownloadOpt = {
  /**
   * iframe下载暂没支持
   *  */
  type?: 'blob' | 'from' | 'open' | 'a',
  contentType?: 'application/json',
  method?: 'POST' | 'GET'
  headers?: MMap,
  corsHeaders?: boolean,
  downloadName?: string,
  withCredentials?: boolean
}
function downloadByGet(func) {
  return function (url, data, opt) {
    return func(joinParamToUrl(url, data), opt)
  }
}
const downloadByLink = downloadByGet(function (url: string, downloadName: string) {
  return new Promise(v => {

    let a = document.createElement('a')
    a.href = url
    a.download = downloadName
    a.click();
  })

})
const downloadByOpen = downloadByGet(function (url) {
  return new Promise(v => {
    window.open(url)
  })
})

function download(url, data: MMap | null = {}, opt?: DownloadOpt) {

  opt = Object.assign({
    contentType: 'application/json',
    corsHeaders: true,
    method: 'POST',
    //   contentType: 'application/x-www-form-urlencoded',
    downloadName: basename(url),
    type: 'blob'
  }, opt)

  switch (opt.type) {
    case 'blob':

      return downloadByBlob(url, data, opt)

    case 'from':
      return downloadByFrom(url, data, opt)

    case 'a':
      return downloadByLink(url, data, opt)

    case 'open':

      return downloadByOpen(url, data, opt)

    // case 'iframe':
    //     downloadByLink(url, data, opt.downloadName)
    //     break;
    default:
      break;
  }
}
function createInput(key, value) {
  let input = document.createElement('input')
  input.setAttribute('type', 'hidden')
  input.value = value;
  input.name = key
  return input
}

export function downloadByFrom(url, data, opt) {
  return new Promise(v => {
    let f = document.createElement('form');
    f.setAttribute('method', 'POST')
    f.setAttribute('action', url)
    f.setAttribute('target', '_self')
    data && Object.keys(data).forEach(v => {
      f.appendChild(createInput(v, data[v]))
    })

    document.body.appendChild(f)
    f.submit();
    setTimeout(function () {
      f.remove()
    }, 300)
  })
}
export function downloadByBlob(url, data, opt: DownloadOpt) {
  return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    if (opt.withCredentials === true) {
      xhr.withCredentials = true
    }
    //   @ts-ignore
    if (opt.method.toLocaleUpperCase() === 'GET') {
      url = joinParamToUrl(url, data)
    }
    xhr.open(opt.method || 'POST', url, true);    // 也可以使用POST方式，根据接口

    let downLink = document.createElement('a')
    downLink.href = url
    //判断同源
    if (downLink.host == location.host || opt.corsHeaders) {

      Object.keys(headers).forEach(v => {
        xhr.setRequestHeader(v, headers[v]);

      })
      opt.headers && Object.keys(opt.headers).forEach(v => {
        //   @ts-ignore
        xhr.setRequestHeader(v, opt.headers[v]);
      })
      //   @ts-ignore
      xhr.setRequestHeader('content-type', opt.contentType);

      xhr.setRequestHeader('response-type', 'stream');
    }

    //   @ts-ignore
    if (opt.contentType.indexOf('application/json') > -1) {
      data = JSON.stringify(data)
      //   @ts-ignore
    } else if (opt.contentType.indexOf('application/x-www-form-urlencoded') > -1) {
      data = serialize(data)
    }
    xhr.responseType = 'blob';

    xhr.onload = function () {
      if (this.status === 200) {
        let a = document.createElement('a');
        a.download = opt.downloadName
        a.href = window.URL.createObjectURL(this.response)
        a.click()
        resolve(true)
      }
    }
    xhr.onerror = function () {
      reject()
    }
    xhr.send(data);
  })

}
function basename(str) {
  // let lastIndex = str.lastIndexOf('/')
  return str.split("/").pop().split("?")[0];
}
/**
* 链接参数到url
* @param url 
* @param data 
*/
function joinParamToUrl(url, data) {
  if (data) {


    if (url.endsWith('?')) {
      url = `${url}${serialize(data)}`
    } else if (url.indexOf('?') > 0) {
      url = `${url}&${serialize(data)}`
    } else {
      url = `${url}?${serialize(data)}`
    }
  }
  return url;
}
function serialize(data) {
  let p: any = [];

  data && Object.keys(data).forEach((key) => {
    if(data[key]!==undefined&&data[key]!==null){
      p.push(`${key}=${data[key]}`)
    }
   
  })
  return p.join('&')
}
let headers = {}
download.setCommonHeader = function (_headers) {
  headers = Object.assign(headers, _headers)
}
export default download
